package com.iot08.admin.service;

import com.iot08.admin.service.page.PageableImpl;
import com.iot08.common.constant.Const;
import com.iot08.common.entity.admin.SysRole;
import com.iot08.common.entity.admin.SysUser;
import com.iot08.common.response.Response;
import com.iot08.common.service.base.BaseAdminService;
import com.iot08.common.utils.UUIDGenerator;
import com.iot08.admin.service.page.PageVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/**
 * @version 1.0
 * @Description: 角色业务处理
 * @author: Rock
 * @time: 2020/8/20 9:51
 */
@Service
public class RoleService extends BaseAdminService<SysRole> {

    @Resource
    private UserService userService;
    @Resource
    private OperationService operationService;

    /**
     * @Description: 角色管理列表
     * @time: 2020/8/20 9:53
     * @author: Rock
     * @version 1.0
     */
    public Page<SysRole> list(PageVO page, SysUser user) {
        PageableImpl pageable = new PageableImpl();
        page.setSort(Sort.by(Order.desc("create_time")));
        pageable.setPage(page);
        Criteria criteria = new Criteria().and("deleted").is(0);
        if (StringUtils.isNotEmpty(page.getSearchValue())) {
            criteria.and("name").regex(".*?" + page.getSearchValue() + ".*?", "i");
        }
        if (user.getType() == Const.CHANNELUSER_TYPE) {
            int areaLevel = user.getChannelArea() == null ? 1 : user.getChannelArea().getLevel();
            criteria.and("level").gte(areaLevel);
            criteria.and("channel_code").in(user.getChannelAff().getChannelCodes());
        }
        Query query = new Query().addCriteria(criteria);
        long count = this.count(query);
        page.setTotalResult((int) count);
        List<SysRole> list = this.find(query.with(pageable));
        Page<SysRole> result = new PageImpl<SysRole>(list, pageable, count);
        return result;
    }

    /**
     * @Description: 删除
     * @time: 2020/8/14 18:58
     * @author: Rock
     * @version 1.0
     */
    public Response<Object> updateDel(String id, SysUser user, String ip) {
        if (userService.countByRoleId(id) > 0) {
            return Response.failedResponse("存在账号引用该角色，无法删除");
        }
        Query query = new Query(Criteria.where("_id").is(id));
        if (query != null) {
            Update update = new Update();
            update.set("deleted", 1);
            update.set("update_time", new Date());
            mongoTemplate.updateFirst(query, update, SysRole.class);
            SysRole role = findById(id);
            operationService.add(user, ip, "角色管理", "删除", "删除角色 ：" + role.getName());
        }
        return Response.successResponse();
    }

    /**
     * @Description: 保存
     * @time: 2020/8/17 17:29
     * @author: Rock
     * @version 1.0
     */
    public void save(SysRole role, SysUser user, String ip) {
        if (role != null) {
            //渠道账号创建的角色，系统自动将该角色分配为渠道归属中第一个渠道所有
            if (user.getType() == Const.CHANNELUSER_TYPE) {
                role.setChannelCode(user.getChannelAff().getChannelCodes().get(0));
            }
            if (Const.INT_0.equals(role.getLevel())) {
                role.setChannelCode(null);
            }
            role.setId(UUIDGenerator.generate());
            role.setDeleted((short) 0);
            role.setCreateTime(new Date());
            mongoTemplate.save(role);
            operationService.add(user, ip, "角色管理", "添加", "添加角色 ：" + role.getName());
        }
    }

    /**
     * @Description: 更新
     * @time: 2020/8/18 10:41
     * @author: Rock
     * @version 1.0
     */
    public void update(SysRole role, SysUser user, String ip) {
        if (role != null) {
            Update update = new Update();
            update.set("name", role.getName());
            update.set("desc", role.getDesc());
            update.set("menu_ids", role.getMenuIds());
            update.set("level", role.getLevel());
            update.set("update_time", new Date());
            if (user.getType() == Const.SYSUSER_TYPE) {
                if (role.getLevel() != null && role.getLevel() > 0) {
                    update.set("channel_code", role.getChannelCode());
                } else {
                    update.unset("channel_code");
                }
            }
            this.updateById(role.getId(), update);
            operationService.add(user, ip, "角色管理", "编辑", "编辑角色 ：" + role.getName());
        }
    }

    /**
     * @Description: 根据等级获取全部角色列表
     * @time: 2020/8/20 16:28
     * @author: Rock
     * @version 1.0
     */
    public List<SysRole> listAll(Integer... level) {
        return this.find(new Query(Criteria.where("deleted").is(0).and("level").in(level)));
    }

    /**
     * @param [menuId]
     * @time: 2020/9/7 17:55
     * @author: Rock
     * @version 1.0
     */
    public Long countByMenuId(String menuId) {
        Query query = new Query(Criteria.where("deleted").is(0).and("menu_ids").regex(".*?" + menuId + ".*?", "i"));
        return mongoTemplate.count(query, SysRole.class);
    }

    /**
     * @param name
     * @time: 2020/11/5 15:24
     * @author: Rock
     * @version 1.0
     */
    public SysRole getByName(String name) {
        return mongoTemplate.findOne(new Query(Criteria.where("name").is(name).and("deleted").is(0)), SysRole.class);
    }

    /**
     * @param level
     * @time: 2020/12/8 18:41
     * @author: Rock
     * @version 1.0
     */
    public List<String> listIdByLevel(Integer... level) {
        List<String> result = new ArrayList<>();
        List<SysRole> roles = this.find(new Query(Criteria.where("level").in(level).and("deleted").is(0)));
        for (SysRole role : roles) {
            result.add(role.getId());
        }
        return result;
    }

    /**
     * @param level
     * @param channelCodes
     * @time: 2020/12/9 14:56
     * @author: Rock
     * @version 1.0
     */
    public List<SysRole> listByLevel(int level, SysUser user) {
        Criteria criteria = Criteria.where("level").gte(level).and("deleted").is(0);
        if (level > 1) {
            criteria.and("channel_code").in(user.getChannelArea().getChannelCode());
        } else {
            criteria.and("channel_code").in(user.getChannelAff().getChannelCodes());
        }
        Query query = new Query(criteria);
        return this.find(query);
    }

}
